/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.web.service.support.storage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ServletContextAware;
import org.vacoor.nothing.web.service.StorageService;
import org.vacoor.nothing.common.util.IOUtils;
import org.vacoor.nothing.common.util.Paths;

import javax.servlet.ServletContext;
import java.io.*;

/**
 * Directory based storage service
 *
 * @author vacoor
 */
public abstract class DirectoryBasedStorageService implements StorageService, ServletContextAware {
    private static final Logger LOG = LoggerFactory.getLogger(DirectoryBasedStorageService.class);

    public static final String DEFAULT_STORAGE_HOME = "/storage";       // 默认存储根目录
    public static final boolean DEFAULT_STORAGE_HOME_RELATIVE = true;   // 存储根目录是否是相对路径

    // @Value("${storage.storeBaseDir:#{systemProperties['java.io.tmpdir']}}")
    private String storageHome;
    private boolean storageHomeRelative;
    private ServletContext servletContext;

    protected DirectoryBasedStorageService() {
        storageHome = DEFAULT_STORAGE_HOME;
        storageHomeRelative = DEFAULT_STORAGE_HOME_RELATIVE;
    }

    @Override
    public boolean exists(String id) {
        return null != readAsFile(id);
    }

    @Override
    public boolean readTo(String id, OutputStream out, boolean closeOut) {
        InputStream is = readAsStream(id);
        if (null == is) {
            return false;
        }
        try {
            IOUtils.flow(is, out, true, closeOut);
        } catch (IOException ioe) {
            LOG.warn("read {} failure: {}", id, ioe);
            return false;
        }
        return true;
    }

    @Override
    public InputStream readAsStream(String id) {
        File file = readAsFile(id);
        try {
            return null == file ? null : new FileInputStream(file);
        } catch (FileNotFoundException fnfe) {
            throw new RuntimeException("不应该出现的异常");
        }
    }


    /**
     * normalize path
     *
     * @param path
     * @return
     */
    protected String normalizePath(String path) {
        return Paths.normalize(path);
    }

    /**
     * 获取相对存储根目录的相对路径
     *
     * @return
     */
    protected String getStorageRelativePath(String realPath) {
        String basePath = getStorageHomeRealPath();
        return Paths.relativize(realPath, basePath);
    }

    /**
     * 获取存储目镜的真实路径
     *
     * @param path
     * @return
     */
    protected String getStorageRealPath(String path) {
        String basePath = getStorageHomeRealPath();
        path = path.startsWith("/") ? path : "/" + path;
        path = !path.endsWith("/") ? path : path.substring(0, path.length() - 1);

        return normalizePath(basePath + path);
    }

    /**
     * 获取存储根目录在文件系统中的路径
     *
     * @return
     */
    protected String getStorageHomeRealPath() {
        String storageHome = getStorageHome();
        String basePath = !isStorageHomeRelative() ? storageHome : servletContext.getRealPath(storageHome);

        return normalizePath(!basePath.endsWith("/") ? basePath : basePath.substring(0, basePath.length() - 1));
    }

    /* ************************
     *  getter / setter
     * ************************/

    public String getStorageHome() {
        return storageHome;
    }

    public void setStorageHome(String storageHome) {
        this.storageHome = normalizePath(storageHome);
    }

    public boolean isStorageHomeRelative() {
        return storageHomeRelative;
    }

    public void setStorageHomeRelative(boolean storageHomeRelative) {
        this.storageHomeRelative = storageHomeRelative;
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
}
